#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include "Wrappers/UnixUtils/Process.hpp"
#include "Wrappers/UnixUtils/Tests/Process_tests.hpp"

namespace wrappers {
namespace unix_utils {

Process_tests::Process_tests()
    : mTestRunner("Processes' tests")
{
  mTestRunner.AddTestCase(UTESTS_MAKE_CASE_DATA(Process_tests::ForkTest));
  mTestRunner.AddTestCase(UTESTS_MAKE_CASE_DATA(Process_tests::KillTest));
  mTestRunner.Run(true);
}

Process_tests::~Process_tests()
{

}

UTESTS_START_TEST(Process_tests::ForkTest)
  {
    Process::GetInstance().SetChildFunction(ForkTest_ChildFunction);
    Process::GetInstance().Fork();
    usleep(1000);
    std::ifstream infile("/tmp/plazza_unittesting_processtests_forktest");
    if (!infile) {
      UTESTS_FAIL("the child didn't create the file");
    }
    else
      infile.close();
  }
  UTESTS_END_TEST

UTESTS_START_TEST(Process_tests::KillTest)
  {
    Process::GetInstance().KillChildren();
    usleep(1000);
    std::ifstream infile("/tmp/plazza_unittesting_processtests_forktest");
    if (infile) {
      infile.close();
      remove("/tmp/plazza_unittesting_processtests_forktest");
      UTESTS_FAIL("the child didn't remove the file");
    }
  }
  UTESTS_END_TEST

void Process_tests::ForkTest_ChildFunction() {
  std::ofstream outfile("/tmp/plazza_unittesting_processtests_forktest");
  outfile.close();
  signal(SIGTERM, ForkTest_ChildFunction_SigHandler);
  while (true)
    usleep(10000);
}

void Process_tests::ForkTest_ChildFunction_SigHandler(int signum) {
  remove("/tmp/plazza_unittesting_processtests_forktest");
  exit(128 + signum);
}

} /* namespace unix_utils */
} /* namespace wrappers */
